package com.aliyun.heiyu.powermaster.server.manager;

import com.aliyun.heiyu.common.util.DateUtil;
import com.aliyun.heiyu.powermaster.proto.PowerInfo;
import com.aliyun.heiyu.powermaster.server.dao.CapFminDao;
import com.aliyun.heiyu.powermaster.server.dao.entity.CapFminEntity;
import com.aliyun.heiyu.powermaster.server.dao.entity.DeviceCommonEntity;
import com.aliyun.heiyu.powermaster.server.dao.impl.CapFminImpl;
import com.aliyun.heiyu.powermaster.server.util.ZkClientUtil;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.*;

public class QosManagerImpl implements QosManager{
    private static Logger logger = LoggerFactory.getLogger(QosManagerImpl.class);

    private static ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2, new BasicThreadFactory.Builder().namingPattern("qos-collect-pool-%d").daemon(true).build());

    private ThunderManager thunderDataProvider;
    private DeviceManagerImpl deviceManager;
    private CapFminDao capDao;
    private static volatile QosManagerImpl instance;

    public static QosManagerImpl getInstance() {
            synchronized (QosManagerImpl.class) {
                if (instance == null) {
                    instance = new QosManagerImpl();
                }
            }

        return instance;
    }

    private QosManagerImpl() {
        thunderDataProvider = new ThunderManagerImpl();
        deviceManager = DeviceManagerImpl.getInstance();
        capDao = new CapFminImpl();

        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    if(ZkClientUtil.checkLeader()){
                        collect();
                    }
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        };
        service.scheduleAtFixedRate(task, 10, 60*60, TimeUnit.SECONDS);
    }

    public CapFminEntity findOne(String deviceId) {
        return capDao.findOne(deviceId);
    }

    public int computingQOS(int value) {
        int qos = 100;
        if (value >= 2500) {
            qos = 100;
        } else if (value == 0) {
            qos = 0;
        } else {
            int a = (2500 - value) % 100;
            int b = a == 0 ? (2500 - value) / 100 : ((2500 - value) / 100 + 1);
            qos = 100 - b;

        }
        return qos;
    }

    private void collect(){
        List<DeviceCommonEntity> all = deviceManager.findAllDeviceCommon();
        if(all != null){
            for(DeviceCommonEntity device : all){
                if(!"server".equals(device.getType())){
                    continue;
                }
                String deviceId = device.getDevice_id();
                CapFminEntity capFminEntity = getCalFmin(deviceId);
                capDao.insert(capFminEntity);
            }
        }
    }

    private CapFminEntity getCalFmin(String deviceId) {
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date time = calendar.getTime();
        String time1 = DateUtil.millisecondToDate(time.getTime());
        String time2 = DateUtil.millisecondToDate(time.getTime() + 60*60*1000);
        String time3 = DateUtil.millisecondToDate(time.getTime() - 24*60*60*1000);
        String time4 = DateUtil.millisecondToDate(time.getTime() - 24*60*60*1000 + 60*60*1000);
        Integer calFmin = getCalFmin(deviceId, time1, time2);
        Integer calFmin1 = getCalFmin(deviceId, time3, time4);
        int ii = calFmin > calFmin1 ? calFmin : calFmin1;
        CapFminEntity capFminEntity = new CapFminEntity();
        capFminEntity.setDevice_id(deviceId);
        capFminEntity.setFmin(ii);
        capFminEntity.setDate(time1);
        capFminEntity.setF_uncapping(2500);
        return capFminEntity;
    }

    private int getCalFmin(String deviceId, String startTime, String endTime){
        PowerInfo maxOne = thunderDataProvider.getMaxOne(deviceId, startTime, endTime);
        if(maxOne == null){
            return 1500;
        }
        double cpuUsage = maxOne.getCpuUsage();
        int maxFreq = 2500;
        double fmin = maxFreq * cpuUsage/100;
        if(fmin < 1500){
            return 1500;
        }
        return (int)fmin;
    }

}
